package it.unicam.fishpass.prism;

/**
 * Evaluates the constants that are present in the expression, both if there are
 * arithmetic or boolean ones. Evaluates also the clock after having initialized
 * them.
 * 
 * @author Andrea Baiocco
 */
public class ConstraintExpression {

	private ConstraintExpression cLeft = null;
	private ConstraintExpression cRight = null;
	private int operator;
	private String var = null;
	private String var2 = null;
	private int num;
	private Boolean bool = null;

	/**
	 * @param bool
	 */
	public ConstraintExpression(boolean bool) {
		this.bool = new Boolean(bool);
	}

	/**
	 * @param var
	 * @param operator
	 * @param num
	 */
	public ConstraintExpression(String var, Integer operator, int num) {
		this.var = var;
		this.operator = operator.intValue();
		this.num = num;
	}

	/**
	 * @param var
	 * @param var2
	 * @param operator
	 * @param num
	 */
	public ConstraintExpression(String var, String var2, Integer operator,
			int num) {
		this.var = var;
		this.var2 = var2;
		this.operator = operator.intValue();
		this.num = num;
	}

	/**
	 * @param cLeft
	 * @param cRight
	 */
	public ConstraintExpression(ConstraintExpression cLeft,
			ConstraintExpression cRight) {
		this.cLeft = cLeft;
		this.cRight = cRight;
	}

	boolean evaluateConstraint(Declaration[] decs, int[] clocks, float[] vars) {
		if (cLeft != null) // Compound constraint
			return cLeft.evaluateConstraint(decs, clocks, vars)
					&& cRight.evaluateConstraint(decs, clocks, vars);
		if (bool != null) // simple boolean constraint (true || false)
			return bool.booleanValue();
		// general constraint ---> a - b # c # = {<, >...}
		float valoreVar1 = Utility.getClockValue(var, decs, clocks, vars);
		float valoreVar2 = var2 != null ? Utility.getClockValue(var2, decs,
				clocks, vars) : 0.0f;
		//
		switch (operator) {
		case (Constant.EQ):
			if (var2 == null)
				return valoreVar1 == num;
			return valoreVar1 - valoreVar2 == num;
		case (Constant.LEQ):
			if (var2 == null)
				return valoreVar1 <= num;
			return valoreVar1 - valoreVar2 <= num;
		case (Constant.LS):
			if (var2 == null)
				return valoreVar1 < num;
			return valoreVar1 - valoreVar2 < num;
		case (Constant.GEQ):
			if (var2 == null)
				return valoreVar1 >= num;
			return valoreVar1 - valoreVar2 >= num;
		case (Constant.GR):
			if (var2 == null)
				return valoreVar1 > num;
			return valoreVar1 - valoreVar2 > num;
		}
		return false;
	}

	@Override
	public String toString() {
		if (cLeft != null)
			return cLeft.toString() + " - AND - " + this.cRight.toString();
		if (var2 != null) // also var must be different!
			return var + " - " + var2 + " " + operator + " " + num;
		if (var != null) // basic case base for only one variable
			return var + "" + "" + Constant.toString(operator) + "" + num;
		return bool.toString(); // if the previous one are not true it is a
								// boolean!
	}
}
